#include "h_iic_s.h"

static void h_iic_s_start(h_iic_s_t *iic_s_t)
{
	iic_s_t->sda_low();
	iic_s_t->scl_low();
}

static void h_iic_s_write_byte(h_iic_s_t *iic_s_t, unsigned char byte)
{
	unsigned char i;
	for(i = 0; i < 8; i++) {
		iic_s_t->scl_low();
		if(byte & 0x80) {
			iic_s_t->sda_high();
		} else {
			iic_s_t->sda_low();
		}
		iic_s_t->scl_high();
		byte <<= 1;
	}
	iic_s_t->scl_low();
	iic_s_t->sda_low();
}

static signed char h_iic_s_wait_ack(h_iic_s_t *iic_s_t)
{
	unsigned short timeout = 0xFF;
	signed char ack;
	iic_s_t->sda_in_init();
	iic_s_t->scl_high();

	while(timeout--) {
		ack = iic_s_t->sda_read();
		if(!ack) {
			break;
		} else {
			iic_s_t->delay_us(5);
		}

	}

	iic_s_t->scl_low();
	iic_s_t->sda_low();
	iic_s_t->sda_out_init();

	return ack;
}

static unsigned char h_iic_s_read_byte(h_iic_s_t *iic_s_t)
{
    unsigned char i, data = 0;
    iic_s_t->sda_in_init();
    for(i = 0; i < 8; i++) {
        data <<= 1;
        iic_s_t->scl_high();
        if(iic_s_t->sda_read()) {
            data |= 0x01;
        }
        
        iic_s_t->scl_low();
    }

    iic_s_t->sda_low();
    iic_s_t->sda_out_init();

    return data;
}

static void h_iic_s_send_ack(h_iic_s_t *iic_s_t, unsigned char ack)
{
    if(ack) {
        iic_s_t->sda_high();
    } else {
        iic_s_t->sda_low();
    }
    iic_s_t->sda_out_init();
    iic_s_t->scl_high();
    iic_s_t->scl_low();
    iic_s_t->sda_low();
}

static void h_iic_s_stop(h_iic_s_t *iic_s_t)
{
	
	iic_s_t->scl_high();
	iic_s_t->sda_high();
}

void h_iic_s_init(h_iic_s_t *iic_s_t)
{
	iic_s_t->sda_out_init();
	iic_s_t->scl_out_init();

	h_iic_s_stop(iic_s_t);
}



h_iic_s_state h_iic_s_write_bytes(h_iic_s_t *iic_s_t, unsigned char address, unsigned char reg, \
									unsigned char *data, unsigned short len)
{
	h_iic_s_start(iic_s_t);
	h_iic_s_write_byte(iic_s_t, address);
	if(h_iic_s_wait_ack(iic_s_t)) {
		return iic_s_address_no_Ack;
	}
	h_iic_s_write_byte(iic_s_t, reg);
	if(h_iic_s_wait_ack(iic_s_t)) {
		return iic_s_reg_no_Ack;
	}
	while(len--) {
		h_iic_s_write_byte(iic_s_t, *data++);
		if(h_iic_s_wait_ack(iic_s_t)) {
			return iic_s_wdata_no_Ack;
		}
	}
	h_iic_s_stop(iic_s_t);
	return iic_s_success;
}

h_iic_s_state h_iic_s_read_bytes(h_iic_s_t *iic_s_t, unsigned char address, unsigned char reg, \
									unsigned char *data, unsigned short len)
{
    h_iic_s_start(iic_s_t);
	h_iic_s_write_byte(iic_s_t, address);
	if(h_iic_s_wait_ack(iic_s_t)) {
		return iic_s_address_no_Ack;
	}
	h_iic_s_write_byte(iic_s_t, reg);
	if(h_iic_s_wait_ack(iic_s_t)) {
		return iic_s_reg_no_Ack;
	}
	h_iic_s_stop(iic_s_t);

	h_iic_s_start(iic_s_t);
	h_iic_s_write_byte(iic_s_t, address | 0x01);
	if(h_iic_s_wait_ack(iic_s_t)) {
		return iic_s_address_no_Ack;
	}
    while(len-- > 1) {
        *data++ = h_iic_s_read_byte(iic_s_t);
        h_iic_s_send_ack(iic_s_t, 0);
    }
    *data++ = h_iic_s_read_byte(iic_s_t);
    h_iic_s_send_ack(iic_s_t, 1);
    h_iic_s_stop(iic_s_t);

    return iic_s_success;
}




